package com.fa4j.system.settings.repository.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONWriter;
import com.fa4j.common.base.model.CommonConstants;
import com.fa4j.common.base.util.TreeUtil;
import com.fa4j.common.data.repository.impl.BaseRepositoryImpl;
import com.fa4j.system.settings.model.Dict;
import com.fa4j.system.settings.model.DictCustomField;
import com.fa4j.system.settings.model.DictValueType;
import com.fa4j.system.settings.repository.DictRepository;
import com.fa4j.system.settings.repository.mapper.DictMapper;
import org.springframework.stereotype.Repository;

import java.io.Serializable;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
 * 系统字典 持久化接口
 *
 * @since 2025-06-12 16:58:22
 */
@Repository
public class DictRepositoryImpl extends BaseRepositoryImpl<DictMapper, Dict> implements DictRepository {

    @Override
    public List<Dict> queryTreeByRootId(Integer rootId, Integer level) {
        return TreeUtil.listToTree(queryListByRootId(rootId, level), rootId);
    }

    @Override
    public List<Dict> queryListByRootId(Integer rootId, Integer level) {
        return super.lambdaQuery()
                .eq(Dict::getRootId, rootId)
                .le(level != null, Dict::getLevel, level)
                .list()
                .stream()
                .map(this::parseDictValue)
                .toList();
    }

    @Override
    public Optional<Dict> findByParentIdAndCode(Integer parentId, String dictCode) {
        return super.lambdaQuery()
                .eq(Dict::getParentId, parentId)
                .eq(Dict::getDictCode, dictCode)
                .oneOpt()
                .map(this::parseDictValue);
    }

    @Override
    public Long countByParentId(Integer parentId) {
        return super.lambdaQuery()
                .eq(Dict::getParentId, parentId).count();
    }

    @Override
    public Optional<Dict> findById(Serializable id) {
        return super.findById(id)
                .map(this::parseDictValue);
    }

    @Override
    public boolean create(Dict entity) {
        customToString(entity);
        return super.create(entity);
    }

    @Override
    public boolean modify(Dict entity) {
        customToString(entity);
        return super.modify(entity);
    }


    private void customToString(Dict entity) {
        if (entity.getValueType() == DictValueType.CUSTOM) {
            if (Objects.equals(entity.getParentId(), CommonConstants.TREE_ROOT_ID)) {
                entity.setDictValue(JSON.toJSONString(entity.getCustomFields()));
            } else {
                entity.setDictValue(JSON.toJSONString(entity.getCustomData(), JSONWriter.Feature.WriteMapNullValue));
            }
        }
    }

    private Dict parseDictValue(Dict entity) {
        if (entity == null) {
            return null;
        }
        if (entity.getValueType() == DictValueType.CUSTOM) {
            if (Objects.equals(entity.getParentId(), CommonConstants.TREE_ROOT_ID)) {
                entity.setCustomFields(JSON.parseArray(entity.getDictValue(), DictCustomField.class));
            } else {
                entity.setCustomData(JSON.parseObject(entity.getDictValue()));
            }
            entity.setDictValue(null);
        }
        return entity;
    }


    @Override
    public List<Dict> queryByParentId(Integer parentId) {
        return super.lambdaQuery()
                .eq(Dict::getParentId, parentId)
                .orderByAsc(Dict::getPriority)
                .list()
                .stream()
                .map(this::parseDictValue)
                .toList();
    }
}
